package tgc.edu.exam.web.controller;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
import java.awt.image.BufferedImage;
import java.text.SimpleDateFormat;

import javax.imageio.ImageIO;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import tgc.edu.exam.custom.CommonController;
import tgc.edu.exam.custom.DataGridUtils;
import tgc.edu.exam.custom.QRCodeUtil;
import tgc.edu.exam.custom.TableGrid;
import tgc.edu.exam.custom.TablePageable;
import tgc.edu.exam.custom.TimeUtils;
import tgc.edu.exam.custom.dict.entity.SystemData;
import tgc.edu.exam.custom.dict.entity.SystemDictionaries;
import tgc.edu.exam.custom.dict.service.SystemDataService;
import tgc.edu.exam.custom.dict.service.SystemDicationariesService;
import tgc.edu.exam.entity.AskForleave;
import tgc.edu.exam.entity.Checkingin;
import tgc.edu.exam.entity.CurriculumPlan;
import tgc.edu.exam.entity.Student;
import tgc.edu.exam.entity.SysRole;
import tgc.edu.exam.entity.SysUser;
import tgc.edu.exam.entity.TbClass;
import tgc.edu.exam.entity.Teacher;
import tgc.edu.exam.security.UserUtils;
import tgc.edu.exam.service.AskForleaveService;
import tgc.edu.exam.service.CheckinginService;
import tgc.edu.exam.service.CurriculumPlanService;
import tgc.edu.exam.service.StudentService;
import tgc.edu.exam.service.TbClassService;
import tgc.edu.exam.service.TbCurriculumService;
import tgc.edu.exam.web.form.CheckinginForm;
import tgc.edu.exam.web.form.StudentForm;

@Controller
@RequestMapping(value = "/checkingin")
public class CheckinginController extends CommonController<Checkingin, UUID, CheckinginForm> {
	@Autowired
	private CheckinginService service;
	@Autowired
	private StudentService stuService;
	@Autowired
	private CurriculumPlanService planservice;
	@Autowired
	private UserUtils userUtils;
	@Autowired
	private TbClassService tbClassService;
	@Autowired
	private SystemDicationariesService dictService;
	@Autowired
	private SystemDataService dataService;
	@Autowired
	private TbCurriculumService tcService;
	@Autowired
	private AskForleaveService askService;

	@Override
	public void edit(CheckinginForm form, ModelMap map) throws InstantiationException, IllegalAccessException {
		SystemDictionaries systemDictionaries = dictService.findByCode("Attendance_status");
		List<SystemData> data = dataService.findBySystemDictionaries(systemDictionaries);
		map.put("data", data);
		super.edit(form, map);
	}

	@Override
	public Specification<Checkingin> buildSpec(CheckinginForm form) {
		Specification<Checkingin> spec = new Specification<Checkingin>() {
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<Checkingin> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				String bjuuid = form.getBjuuid();
				if (StringUtils.hasText(bjuuid)) {
					rules.add(cb.equal(root.get("bjuuid"), bjuuid));
				}
				String suuid = form.getSuuid();
				if (StringUtils.hasText(suuid)) {
					rules.add(cb.equal(root.get("student").get("id"), UUID.fromString(suuid)));
				}
				String curriculumPlan = form.getCurriculumPlan();
				if (StringUtils.hasText(curriculumPlan)) {
					rules.add(cb.equal(root.get("curriculumName"), curriculumPlan));
				}

				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}

	@Override
	public void manage(ModelMap map) {
		boolean ishas = false;
		SysUser sysUser = userUtils.getUser();
		if (sysUser == null) {
			ishas = true;
			Specification<TbClass> spec = buildSpec3(null);
			List<TbClass> bjs = tbClassService.findAll(spec);
			Specification<Student> spec1 = buildSpec4(bjs.get(0));
			List<Student> list = stuService.findAll(spec1);
			map.put("stu", list);
			map.put("bjs", bjs);
		} else {
			List<SysRole> roles = sysUser.getRoles();
			for (SysRole sysRole : roles) {
				List<SysRole> childrens = sysRole.getChildren();
				for (SysRole sysRole2 : childrens) {
					if (sysRole2.getCode().equals("ROLE_KAOQINGEDIT")) {
						ishas = true;
					}
				}
			}
			if (ishas) {
				Specification<TbClass> spec = buildSpec3(null);
				List<TbClass> bjs = tbClassService.findAll(spec);
				Specification<Student> spec1 = buildSpec4(bjs.get(0));
				List<Student> list = stuService.findAll(spec1);
				map.put("bjs", bjs);
				map.put("stu", list);
			} else {
				Specification<TbClass> spec = buildSpec3(sysUser);
				List<TbClass> bjs = tbClassService.findAll(spec);
				Specification<Student> spec1 = buildSpec4(bjs.get(0));
				List<Student> list = stuService.findAll(spec1);
				map.put("bjs", bjs);
				map.put("stu", list);
			}

		}
		map.put("kc", tcService.findAll());
		super.manage(map);
	}

	private Specification<TbClass> buildSpec3(SysUser sysUser) {
		Specification<TbClass> spec = new Specification<TbClass>() {
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<TbClass> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				if (sysUser != null) {
					rules.add(cb.equal(root.get("teacherId").get("id"), sysUser.getId()));
				}
				rules.add(cb.notEqual(root.get("classStatus").get("state"), "结业"));
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}

	@RequestMapping(value = "select")
	@ResponseBody
	public Object select(String id) {
		TbClass tbClass = tbClassService.findById(UUID.fromString(id));
		Specification<Student> spec = buildSpec4(tbClass);
		List<Student> list = stuService.findAll(spec);
		return list;
	}

	@RequestMapping(value = "/qiandao")
	public void qiandao(ModelMap map, HttpSession session) {
		/*
		 * Teacher teacher = (Teacher) userUtils.getUser();
		 * Specification<CurriculumPlan> spec = new Specification<CurriculumPlan>() {
		 * private static final long serialVersionUID = 1L;
		 * 
		 * @Override public Predicate toPredicate(Root<CurriculumPlan> root,
		 * CriteriaQuery<?> query, CriteriaBuilder cb) { HashSet<Predicate> rules = new
		 * HashSet<>(); rules.add(cb.greaterThanOrEqualTo(root.get("starttime"),
		 * TimeUtils.getDateTime())); System.out.println(TimeUtils.getDateTime());
		 * rules.add(cb.lessThanOrEqualTo(root.get("finishttime"),
		 * TimeUtils.getDateTime()));
		 * rules.add(cb.equal(root.get("teacher").get("name"), teacher.getName()));
		 * return cb.and(rules.toArray(new Predicate[rules.size()])); } };
		 * List<CurriculumPlan> findAll = planservice.findAll(spec); CurriculumPlan plan
		 * = new CurriculumPlan(); if (findAll.size() != 0) { plan = findAll.get(0);
		 * session.setAttribute("plan", plan); session.setMaxInactiveInterval(30 * 60);
		 * map.put("plan", plan); }
		 */
	}

	@RequestMapping(value = "/page1")
	@ResponseBody
	public Object Page1(TablePageable pageParam) {
		PageRequest pageable = pageParam.bulidPageRequest();
		Page<CurriculumPlan> page = null;
		Teacher teacher = (Teacher) userUtils.getUser();
		Specification<CurriculumPlan> spec1 = buildSpec1(teacher);
		page = planservice.findAll(spec1, pageable);
		return DataGridUtils.buildResult(page);
	}

	private Specification<CurriculumPlan> buildSpec1(Teacher teacher) {
		Specification<CurriculumPlan> spec = new Specification<CurriculumPlan>() {
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<CurriculumPlan> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				rules.add(cb.greaterThanOrEqualTo(root.get("finishttime"), TimeUtils.getDateTime()));
				if (teacher != null) {
					rules.add(cb.equal(root.get("curriculum").get("teacher").get("id"), teacher.getId()));
				}
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}

	/*
	 * private Specification<Checkingin> buildSpec2(CurriculumPlan plan, Teacher
	 * teacher) { Specification<Checkingin> spec = new Specification<Checkingin>() {
	 * private static final long serialVersionUID = 1L;
	 * 
	 * @Override public Predicate toPredicate(Root<Checkingin> root,
	 * CriteriaQuery<?> query, CriteriaBuilder cb) { HashSet<Predicate> rules = new
	 * HashSet<>(); rules.add(cb.greaterThanOrEqualTo(root.get("time"),
	 * plan.getFinishttime())); rules.add(cb.lessThanOrEqualTo(root.get("time"),
	 * plan.getStarttime()));
	 * rules.add(cb.equal(root.get("student").get("tbClass").get("teacherId"),
	 * teacher)); return cb.and(rules.toArray(new Predicate[rules.size()])); } };
	 * return spec; }
	 */

	@RequestMapping(value = "/scerw")
	public void scerw(String id, ModelMap map) {
		map.put("planid", id);
	}

	@RequestMapping(value = "/erweim")
	@ResponseBody
	public void erweim(HttpServletRequest req, HttpServletResponse resp, String planid) {
		try {
			ServletOutputStream sos;
			String text = "无课程";
			boolean ishao = false;
			CurriculumPlan plan = planservice.findById(UUID.fromString(planid));
			text = planid;
			if (plan.getIsUsed()) {
				TbClass tbclass = plan.getTbClass();
				Specification<Student> spec = buildSpec4(tbclass);
				List<Student> list = stuService.findAll(spec);
				for (Student student : list) {
					Specification<AskForleave> spec1 = buildSpec1(student.getId());
					List<AskForleave> asks = askService.findAll(spec1);
					for (AskForleave ask : asks) {
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						Date startDate =sdf.parse(ask.getStartDate());
						Date endDate = sdf.parse(ask.getEndDate());
						if(TimeUtils.AfterTime(startDate)&&TimeUtils.BeforeTime(endDate)) {
							ishao = true;
						}
					}
					Checkingin chenckingin = new Checkingin();
					chenckingin.setCurriculumName(plan.getCurriculum().getCourseName() + "("+ plan.getCurriculum().getTeacher().getName() + ")");
					chenckingin.setCurriculumPlan(plan.getId());
					chenckingin.setDates(plan.getStartdata());
					if(ishao) {
						chenckingin.setIsReach("请假");
					}else {
						chenckingin.setIsReach("旷课");
					}
					chenckingin.setStudent(student);
					chenckingin.setBjuuid(tbclass.getId().toString());
					chenckingin.setBanji(tbclass.getName());
					service.save(chenckingin);
				}
				plan.setIsUsed(false);
				planservice.save(plan);
			}

			resp.setHeader("Pragma", "no-cache");
			resp.setHeader("Cache-Control", "no-cache");
			resp.setDateHeader("Expires", -1);
			resp.setContentType("image/jpeg");
			sos = resp.getOutputStream();
			BufferedImage image = QRCodeUtil.createImage1(text, null, false);
			ImageIO.write(image, "jpeg", sos);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private Specification<Student> buildSpec4(TbClass tbClass2) {
		Specification<Student> spec = new Specification<Student>() {

			@Override
			public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();

				rules.add(cb.equal(root.get("tbClass").get("id"), tbClass2.getId()));
				rules.add(cb.equal(root.get("isUsed"), true));

				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}

	private Specification<AskForleave> buildSpec1(UUID id) {

		Specification<AskForleave> spec = new Specification<AskForleave>() {

			@Override
			public Predicate toPredicate(Root<AskForleave> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				rules.add(cb.equal(root.get("studentId"), id));
				rules.add(cb.equal(root.get("state"), 2));
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}

	/*
	 * @RequestMapping(value="/isYes")
	 * 
	 * @ResponseBody public Object isYes(String stuid,String planid) { String msg
	 * ="操作失败！"; if((stuid!=null&&stuid!="")&&(planid!=null&&planid!="")) { Student
	 * student = stuService.findById(UUID.fromString(stuid)); CurriculumPlan
	 * curriculumPlan = planservice.findById(UUID.fromString(planid)); Checkingin
	 * checkingin = new Checkingin(); checkingin.setCurriculumPlan(curriculumPlan);
	 * checkingin.setStudent(student);
	 * checkingin.setTime(TimeUtils.getStringDate()); checkingin.setIsReach("已到");
	 * service.save(checkingin); msg="操作成功！"; } return msg;
	 * 
	 * }
	 * 
	 * @RequestMapping(value="/isLeave")
	 * 
	 * @ResponseBody public Object isLeave(String stuid,String planid) { String msg
	 * ="操作失败！"; if((stuid!=null&&stuid!="")&&(planid!=null&&planid!="")) { Student
	 * student = stuService.findById(UUID.fromString(stuid)); CurriculumPlan
	 * curriculumPlan = planservice.findById(UUID.fromString(planid)); Checkingin
	 * checkingin = new Checkingin(); checkingin.setCurriculumPlan(curriculumPlan);
	 * checkingin.setStudent(student);
	 * checkingin.setTime(TimeUtils.getStringDate()); checkingin.setIsReach("请假");
	 * service.save(checkingin); msg="操作成功！"; } return msg;
	 * 
	 * }
	 * 
	 * @RequestMapping(value="/isNo")
	 * 
	 * @ResponseBody public Object isNo(String stuid,String planid) { String msg
	 * ="操作失败！"; if((stuid!=null&&stuid!="")&&(planid!=null&&planid!="")) { Student
	 * student = stuService.findById(UUID.fromString(stuid)); CurriculumPlan
	 * curriculumPlan = planservice.findById(UUID.fromString(planid)); Checkingin
	 * checkingin = new Checkingin(); checkingin.setCurriculumPlan(curriculumPlan);
	 * checkingin.setStudent(student);
	 * checkingin.setTime(TimeUtils.getStringDate()); checkingin.setIsReach("未到");
	 * service.save(checkingin); msg="操作成功！"; } return msg;
	 * 
	 * }
	 * 
	 * @RequestMapping(value="/quanqin")
	 * 
	 * @ResponseBody public Object quanqin(HttpSession session) { String msg
	 * ="操作失败！"; CurriculumPlan plan = (CurriculumPlan)
	 * session.getAttribute("plan"); if(plan!=null) { Teacher teacher = (Teacher)
	 * userUtils.getUser(); Specification<Checkingin> spec =
	 * buildSpec2(plan,teacher); List<Checkingin> checkingins =
	 * service.findAll(spec); Specification<Student> spec1 =
	 * buildSpec1(teacher,checkingins); List<Student>
	 * students=stuService.findAll(spec1); for (Student student : students) {
	 * Checkingin checkingin = new Checkingin(); checkingin.setCurriculumPlan(plan);
	 * checkingin.setStudent(student);
	 * checkingin.setTime(TimeUtils.getStringDate()); checkingin.setIsReach("已到");
	 * service.save(checkingin); } msg="操作成功！"; } return msg;
	 * 
	 * }
	 */

}
